package com.example.ecommercemarketing.service;

import com.example.common.Util;
import com.example.ecommercemarketing.helper.RecommendMerchantHelper;
import com.example.ecommercemarketing.helper.RecommendProductHelper;
import com.example.ecommercemarketing.entity.Merchant;
import com.example.ecommercemarketing.entity.Product;
import com.example.ecommercemarketing.exception.RecommendServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 推荐商品服务类 - 提供推荐商品相关功能.
 */
@Service
@Slf4j
public class RecommendService {
    /**
     * 使用Ttl包装的“产品中心通用线程池”
     */
    @Resource(name = "productCenterThreadPoolTtl")
    private Executor productCenterThreadPoolTtl;
    @Resource
    private RecommendMerchantHelper recommendMerchantHelper;
    @Resource
    private RecommendProductHelper recommendProductHelper;

    /**
     * 根据优先推荐的商户获取推荐商品列表
     *
     * @return
     * @throws RuntimeException 如果查询过程中出现超时或其他错误
     */
    public List<Product> getRecommendProductsByMerchant() {
        // 1. 获取优先推荐的商户列表（已按业务规则排序）
        List<Merchant> merchantList = recommendMerchantHelper.getRecommendMerchantList();

        // 2. 创建线程安全的集合用于存储结果
        List<Product> resultList = new CopyOnWriteArrayList<>();

        // 3. 创建并执行所有异步查询任务
        List<CompletableFuture<Void>> futures = merchantList.stream()
                .map(merchant -> CompletableFuture
                        // 异步查询该商户的推荐商品
                        .supplyAsync(() -> recommendProductHelper.queryRecommendProduct(merchant), productCenterThreadPoolTtl)
                        // 成功回调：处理查询结果
                        .thenAccept(products -> collectProducts(products, resultList))
                        // 异常处理：记录失败并返回空列表
                        .exceptionally(ex -> dealException(merchant, ex)))
                .collect(Collectors.toList());

        // 4. 组合所有任务
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
                futures.toArray(new CompletableFuture[0]));

        try {
            // 5. 阻塞等待所有异步任务完成（最大等待10秒）
            allFutures.get(10, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            log.error("商品查询超时，已完成{}个/共{}个商户",
                    futures.stream().filter(CompletableFuture::isDone).count(),
                    futures.size());
        } catch (InterruptedException | ExecutionException e) {
            Thread.currentThread().interrupt();
            throw new RecommendServiceException("推荐服务中断", e);
        } finally {
            // 6. 资源清理
            futures.forEach(f -> f.cancel(true));
        }

        return resultList;
    }

    /**
     * 汇总商品到resultList中
     *
     * @param products   产品列表
     * @param resultList 汇总后的产品列表
     */
    private static void collectProducts(List<Product> products, List<Product> resultList) {
        if (!Util.isNullOrEmpty(products)) {
            resultList.addAll(products);
        }
    }

    /**
     * 用于“异步查询各个商户的推荐商品”时的异常处理
     *
     * @param merchant 商户
     * @param ex       异常
     * @return
     */
    private static Void dealException(Merchant merchant, Throwable ex) {
        log.error("Query failed for merchant: {}", merchant.getId(), ex);
        return null;
    }
}
